/*
 * Copyright (C) 2012 Matt Broadstone
 * Contact: http://code.google.com/p/qconnman/
 *
 * This file is part of the QConnman Library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

#ifndef SERVICE_H
#define SERVICE_H

#include <QObject>
#include <QStringList>
#include <QDBusObjectPath>
#include <QDBusArgument>

#include "types.h"
#include "connmanobject.h"

class Service;
class ConfigurableObject : public QObject
{
    Q_OBJECT
public:
    explicit ConfigurableObject(Service *parent);
    void apply();

};

class IPV4Data : public ConfigurableObject
{
    Q_OBJECT
    Q_PROPERTY(QString Method READ method WRITE setMethod)
    Q_PROPERTY(QString Address READ address WRITE setAddress)
    Q_PROPERTY(QString Netmask READ netmask WRITE setNetmask)
    Q_PROPERTY(QString Gateway READ gateway WRITE setGateway)
public:
    explicit IPV4Data(Service *parent);
    ~IPV4Data();

    QString method() const;
    void setMethod(const QString &method);

    QString address() const;
    void setAddress(const QString &address);

    QString netmask() const;
    void setNetmask(const QString &netmask);

    QString gateway() const;
    void setGateway(const QString &gateway);

private:
    QString m_method;
    QString m_address;
    QString m_netmask;
    QString m_gateway;

};

class IPV6Data : public ConfigurableObject
{
    Q_OBJECT
    Q_PROPERTY(QString Method READ method WRITE setMethod)
    Q_PROPERTY(QString Address READ address WRITE setAddress)
    Q_PROPERTY(QString PrefixLength READ prefixLength WRITE setPrefixLength)
    Q_PROPERTY(QString Gateway READ gateway WRITE setGateway)
    Q_PROPERTY(QString Privacy READ privacy WRITE setPrivacy)
public:
    explicit IPV6Data(Service *parent);
    ~IPV6Data();

    QString method() const;
    void setMethod(const QString &method);

    QString address() const;
    void setAddress(const QString &address);

    QString prefixLength() const;
    void setPrefixLength(const QString &prefixLength);

    QString gateway() const;
    void setGateway(const QString &gateway);

    QString privacy() const;
    void setPrivacy(const QString &privacy);

private:
    QString m_method;
    QString m_address;
    QString m_prefixLength;
    QString m_gateway;
    QString m_privacy;

};

class ProxyData : public ConfigurableObject
{
    Q_OBJECT
    Q_PROPERTY(QString Method READ method WRITE setMethod)
    Q_PROPERTY(QString URL READ url WRITE setUrl)
    Q_PROPERTY(QStringList Servers READ servers WRITE setServers)
    Q_PROPERTY(QStringList Excludes READ excludes WRITE setExcludes)
public:
    explicit ProxyData(Service *parent);
    ~ProxyData();

    QString method() const;
    void setMethod(const QString &method);

    QString url() const;
    void setUrl(const QString &url);

    QStringList servers() const;
    void setServers(const QStringList &servers);

    QStringList excludes() const;
    void setExcludes(const QStringList &excludes);

private:
    QString m_method;
    QString m_url;
    QStringList m_servers;
    QStringList m_excludes;

};

class ProviderData : public ConfigurableObject
{
    Q_OBJECT
    Q_PROPERTY(QString Host READ host WRITE setHost)
    Q_PROPERTY(QString Domain READ domain WRITE setDomain)
    Q_PROPERTY(QString Name READ name WRITE setName)
    Q_PROPERTY(QString Type READ type WRITE setType)
public:
    explicit ProviderData(Service *parent);
    ~ProviderData();

    QString host() const;
    void setHost(const QString &host);

    QString domain() const;
    void setDomain(const QString &domain);

    QString name() const;
    void setName(const QString &name);

    QString type() const;
    void setType(const QString &type);

private:
    QString m_host;
    QString m_domain;
    QString m_name;
    QString m_type;

};

class EthernetData : public ConfigurableObject
{
    Q_OBJECT
    Q_PROPERTY(QString Method READ method WRITE setMethod)
    Q_PROPERTY(QString Interface READ interface WRITE setInterface)
    Q_PROPERTY(QString Address READ address WRITE setAddress)
    Q_PROPERTY(quint16 MTU READ mtu WRITE setMtu)
    Q_PROPERTY(quint16 Speed READ speed WRITE setSpeed)
    Q_PROPERTY(QString Duplex READ duplex WRITE setDuplex)
public:
    EthernetData(Service *parent);
    ~EthernetData();

    QString method() const;
    void setMethod(const QString &method);

    QString interface() const;
    void setInterface(const QString &interface);

    QString address() const;
    void setAddress(const QString &address);

    quint16 mtu() const;
    void setMtu(quint16 mtu);

    quint16 speed() const;
    void setSpeed(quint16 speed);

    QString duplex() const;
    void setDuplex(const QString &duplex);

private:
    QString m_method;
    QString m_interface;
    QString m_address;
    quint16 m_mtu;
    quint16 m_speed;
    QString m_duplex;

};

class ServiceInterface;
class Service : public ConnManObject
{
    Q_OBJECT
    Q_ENUMS(ServiceState)
    Q_PROPERTY(QString State READ stateInternal WRITE setStateInternal NOTIFY dataChanged)
    Q_PROPERTY(QString Error READ error WRITE setErrorInternal NOTIFY dataChanged)
    Q_PROPERTY(QString Name READ name WRITE setNameInternal NOTIFY dataChanged)
    Q_PROPERTY(QString Type READ type WRITE setTypeInternal NOTIFY dataChanged)
    Q_PROPERTY(QStringList Security READ security WRITE setSecurityInternal NOTIFY dataChanged)
    Q_PROPERTY(quint8 Strength READ strength WRITE setStrengthInternal NOTIFY dataChanged)
    Q_PROPERTY(bool Favorite READ isFavorite WRITE setFavoriteInternal NOTIFY dataChanged)
    Q_PROPERTY(bool Immutable READ isImmutable WRITE setImmutableInternal NOTIFY dataChanged)
    Q_PROPERTY(bool AutoConnect READ isAutoConnect WRITE setAutoConnectInternal NOTIFY dataChanged)
    Q_PROPERTY(bool Roaming READ isRoaming WRITE setRoamingInternal NOTIFY dataChanged)
    Q_PROPERTY(QStringList Nameservers READ nameservers WRITE setNameserversInternal NOTIFY dataChanged)
    Q_PROPERTY(QStringList NameserversConfiguration READ nameserversConfiguration WRITE setNameserversConfigurationInternal NOTIFY dataChanged)
    Q_PROPERTY(QStringList Timeservers READ timeservers WRITE setTimeserversInternal NOTIFY dataChanged)
    Q_PROPERTY(QStringList TimeserversConfiguration READ timeserversConfiguration WRITE setTimeserversConfigurationInternal NOTIFY dataChanged)
    Q_PROPERTY(QStringList Domains READ domains WRITE setDomainsInternal NOTIFY dataChanged)
    Q_PROPERTY(QStringList DomainsConfiguration READ domainsConfiguration WRITE setDomainsConfigurationInternal NOTIFY dataChanged)

    Q_PROPERTY(EthernetData *Ethernet READ ethernet)
    Q_PROPERTY(EthernetData *EthernetConfiguration READ ethernetConfiguration)
    Q_PROPERTY(IPV4Data *IPv4 READ ipv4)
    Q_PROPERTY(IPV4Data *IPv4Configuration READ ipv4Configuration)
    Q_PROPERTY(IPV6Data *IPv6 READ ipv6)
    Q_PROPERTY(IPV6Data *IPv6Configuration READ ipv6Configuration)
    Q_PROPERTY(ProxyData *Proxy READ proxy)
    Q_PROPERTY(ProxyData *ProxyConfiguration READ proxyConfiguration)
    Q_PROPERTY(ProviderData *Provider READ provider)
    Q_PROPERTY(ProviderData *ProviderConfiguration READ providerConfiguration)

public:
    enum ServiceState { UndefinedState, IdleState, FailureState, AssociationState, ConfigurationState, ReadyState, DisconnectState, OnlineState };
    Service(const ObjectPropertyData &info, QObject *parent = 0);
    ~Service();

    QDBusObjectPath objectPath() const;
    ServiceState state() const;
    QString error() const;
    QString name() const;
    QString type() const;
    QStringList security() const;
    quint8 strength() const;
    bool isFavorite() const;
    bool isImmutable() const;
    bool isRoaming() const;

    bool isAutoConnect() const;
    void setAutoConnect(bool autoConnect);

    QStringList nameservers() const;
    QStringList nameserversConfiguration() const;
    void setNameserversConfiguration(const QStringList &nameServers);

    QStringList timeservers() const;
    QStringList timeserversConfiguration() const;
    void setTimeserversConfiguration(const QStringList &timeServers);

    QStringList domains() const;
    QStringList domainsConfiguration() const;
    void setDomainsConfiguration(const QStringList &domains);

    EthernetData *ethernet() const;
    EthernetData *ethernetConfiguration() const;

    IPV4Data *ipv4() const;
    IPV4Data *ipv4Configuration() const;

    IPV6Data *ipv6() const;
    IPV6Data *ipv6Configuration() const;

    ProxyData *proxy() const;
    ProxyData *proxyConfiguration() const;

    ProviderData *provider() const;
    ProviderData *providerConfiguration() const;

Q_SIGNALS:
    void stateChanged();
    void dataChanged();

public Q_SLOTS:
    void connect();
    void disconnect();
    void remove();
    void moveBefore(Service *service);
    void moveAfter(Service *service);
    void resetCounters();

private Q_SLOTS:
    void propertyChanged(const QString &property, const QDBusVariant &value);

private:
    QString stateInternal() const;
    void setStateInternal(const QString &state);
    void setAutoConnectInternal(bool autoConnect);
    void setDomainsInternal(const QStringList &domains);
    void setTimeserversInternal(const QStringList &servers);
    void setNameserversInternal(const QStringList &servers);
    void setNameserversConfigurationInternal(const QStringList &nameServers);
    void setTimeserversConfigurationInternal(const QStringList &timeServers);
    void setDomainsConfigurationInternal(const QStringList &domains);
    void setErrorInternal(const QString &error);
    void setNameInternal(const QString &name);
    void setTypeInternal(const QString &type);
    void setSecurityInternal(const QStringList &security);
    void setStrengthInternal(quint8 strength);
    void setFavoriteInternal(bool favorite);
    void setImmutableInternal(bool immutable);
    void setRoamingInternal(bool roaming);

    ServiceInterface *m_serviceInterface;

    QDBusObjectPath m_objectPath;
    QString m_state;
    QString m_error;
    QString m_name;
    QString m_type;
    QStringList m_security;
    quint8 m_strength;
    bool m_favorite;
    bool m_immutable;
    bool m_autoConnect;
    bool m_roaming;
    QStringList m_nameservers;
    QStringList m_nameserversConfiguration;
    QStringList m_timeservers;
    QStringList m_timeserversConfiguration;
    QStringList m_domains;
    QStringList m_domainsConfiguration;

    EthernetData *m_ethernet;
    EthernetData *m_ethernetConfiguration;
    IPV4Data *m_ipv4;
    IPV4Data *m_ipv4Configuration;
    IPV6Data *m_ipv6;
    IPV6Data *m_ipv6Configuration;
    ProxyData *m_proxy;
    ProxyData *m_proxyConfiguration;
    ProviderData *m_provider;
    ProviderData *m_providerConfiguration;

    friend class ConfigurableObject;
};
Q_DECLARE_METATYPE(Service*)

QDebug operator<<(QDebug, const Service *);
QDebug operator<<(QDebug, const ConfigurableObject *);

#endif

